home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Magnum One
/
Magnum One (Mid-American Digital) (Disc Manufacturing).iso
/
d13
/
phantz.arc
/
PHANT2.Z
/
PHANT2
Wrap
Text File
|
1991-06-06
|
60KB
|
2,153 lines
: ---------CUT HERE---------
: This is a shar archive. Extract with sh, not csh.
: The rest of this file will extract:
: phantglobs.h phantglobs.c fight.c convert.c
echo x - phantglobs.h
sed 's/^X//' > phantglobs.h << '!EOR!'
X/*
X * phantglobs.h - global declarations for Phantasia
X */
X
Xextern double Circle; /* which circle player is in */
Xextern double Shield; /* force field thrown up in monster battle */
X
Xextern bool Beyond; /* set if player is beyond point of no return */
Xextern bool Marsh; /* set if player is in dead marshes */
Xextern bool Throne; /* set if player is on throne */
Xextern bool Changed; /* set if important player stats have changed */
Xextern bool Wizard; /* set if player is the 'wizard' of the game */
Xextern bool Timeout; /* set if short timeout waiting for input */
Xextern bool Windows; /* set if we are set up for curses stuff */
Xextern bool Luckout; /* set if we have tried to luck out in fight */
Xextern bool Foestrikes; /* set if foe gets a chance to hit in battleplayer()*/
Xextern bool Echo; /* set if echo input to terminal */
X
Xextern int Users; /* number of users currently playing */
Xextern int Whichmonster; /* which monster we are fighting */
Xextern int Lines; /* line on screen counter for fight routines */
X#ifdef OK_TO_PLAY
Xextern int Okcount; /* counter for checking ok_to_play */
X#endif
X
Xextern jmp_buf Fightenv; /* used to jump into fight routine */
Xextern jmp_buf Timeoenv; /* used for timing out waiting for input */
X
Xextern long Fileloc; /* location in file of player statistics */
X
Xextern char *Login; /* pointer to login of current player */
Xextern char *Enemyname; /* pointer name of monster/player we are battling*/
X
Xextern struct player Player; /* stats for player */
Xextern struct player Other; /* stats for another player */
X
Xextern struct monster Curmonster;/* stats for current monster */
X
Xextern struct energyvoid Enrgyvoid;/* energy void buffer */
X
Xextern struct charstats Stattable[];/* used for rolling and changing player stats*/
X
Xextern struct charstats *Statptr;/* pointer into Stattable[] */
X
Xextern struct menuitem Menu[]; /* menu of items for purchase */
X
Xextern FILE *Playersfp; /* pointer to open player file */
Xextern FILE *Monstfp; /* pointer to open monster file */
Xextern FILE *Messagefp; /* pointer to open message file */
Xextern FILE *Energyvoidfp; /* pointer to open energy void file */
X
Xextern char Databuf[]; /* a place to read data into */
X
X/* edit these path definitions to let files reside elsewhere */
Xextern char Monstfile[]; /* monster database */
Xextern char Peoplefile[]; /* player database */
Xextern char Gameprog[]; /* game binary */
Xextern char Messfile[]; /* player to player messages */
Xextern char Lastdead[]; /* data on last player killed */
Xextern char Helpfile[]; /* manual pages */
Xextern char Motdfile[]; /* message from 'wizard' */
Xextern char Goldfile[]; /* gold collected in taxes */
Xextern char Voidfile[]; /* energy void database */
Xextern char Scorefile[]; /* hi score database */
X#ifdef ENEMY
Xextern char Enemyfile[]; /* restricted account database */
X#endif
X
X/* some canned strings for messages */
Xextern char Illcmd[];
Xextern char Illmove[];
Xextern char Illspell[];
Xextern char Nomana[];
Xextern char Somebetter[];
Xextern char Nobetter[];
X
X/* library functions and system calls */
Xextern long time();
Xextern char *getlogin();
Xextern char *getpass();
Xextern char *strchr();
Xextern char *strcat();
Xextern char *strcpy();
Xextern char *strncpy();
Xextern char *getenv();
Xstruct passwd *getpwuid();
Xextern char *fgets();
X
X/* functions which we need to know about */
Xextern int interrupt();
Xextern int ill_sig();
Xextern int catchalarm();
Xextern long recallplayer();
Xextern long findname();
Xextern long allocrecord();
Xextern long rollnewplayer();
Xextern long allocvoid();
Xextern double random();
Xextern double distance();
Xextern double infloat();
Xextern double explevel();
Xextern char *descrlocation();
Xextern char *descrtype();
Xextern char *descrstatus();
!EOR!
echo x - phantglobs.c
sed 's/^X//' > phantglobs.c << '!EOR!'
X/*
X * phantglobs.c - globals for Phantasia
X */
X
X#include "include.h"
X
Xdouble Circle; /* which circle player is in */
Xdouble Shield; /* force field thrown up in monster battle */
X
Xbool Beyond; /* set if player is beyond point of no return */
Xbool Marsh; /* set if player is in dead marshes */
Xbool Throne; /* set if player is on throne */
Xbool Changed; /* set if important player stats have changed */
Xbool Wizard; /* set if player is the 'wizard' of the game */
Xbool Timeout; /* set if short timeout waiting for input */
Xbool Windows; /* set if we are set up for curses stuff */
Xbool Luckout; /* set if we have tried to luck out in fight */
Xbool Foestrikes; /* set if foe gets a chance to hit in battleplayer() */
Xbool Echo; /* set if echo input to terminal */
X
Xint Users; /* number of users currently playing */
Xint Whichmonster; /* which monster we are fighting */
Xint Lines; /* line on screen counter for fight routines */
X#ifdef OK_TO_PLAY
Xint Okcount; /* counter for checking ok_to_play */
X#endif
X
Xjmp_buf Fightenv; /* used to jump into fight routine */
Xjmp_buf Timeoenv; /* used for timing out waiting for input */
X
Xlong Fileloc; /* location in file of player statistics */
X
Xchar *Login; /* pointer to login of player */
Xchar *Enemyname; /* pointer name of monster/player we are battling*/
X
Xstruct player Player; /* stats for player */
Xstruct player Other; /* stats for another player */
X
Xstruct monster Curmonster;/* stats for current monster */
X
Xstruct energyvoid Enrgyvoid;/* energy void buffer */
X
Xstruct charstats *Statptr;/* pointer into Stattable[] */
X
X/* lookup table for character type dependent statistics */
Xstruct charstats Stattable[7] =
X {
X /* MAGIC USER */
X /* max brains, max mana, weakness, gold tote, ring duration */
X 15.0, 200.0, 18.0, 175.0, 10,
X /* quickness strength mana energy brains magic lvl */
X 30, 6, 0.0, 10, 6, 2.0, 50,51,75.0, 30,16,20.0, 60,26, 6.0, 5, 5,2.75,
X
X /* FIGHTER */
X /* max brains, max mana, weakness, gold tote, ring duration */
X 10.0, 110.0, 15.0, 220.0, 20,
X /* quickness strength mana energy brains magic lvl */
X 30, 6, 0.0, 40,16, 3.0, 30,21,40.0, 45,26,30.0, 25,21, 3.0, 3, 4, 1.5,
X
X /* ELF */
X /* max brains, max mana, weakness, gold tote, ring duration */
X 12.0, 150.0, 17.0, 190.0, 13,
X /* quickness strength mana energy brains magic lvl */
X 32, 7, 0.0, 35,11, 2.5, 45,46,65.0, 30,21,25.0, 40,26, 4.0, 4, 4, 2.0,
X
X /* DWARF */
X /* max brains, max mana, weakness, gold tote, ring duration */
X 7.0, 80.0, 13.0, 255.0, 25,
X /* quickness strength mana energy brains magic lvl */
X 25, 6, 0.0, 50,21, 5.0, 25,21,30.0, 60,41,35.0, 20,21, 2.5, 2, 4, 1.0,
X
X /* HALFLING */
X /* max brains, max mana, weakness, gold tote, ring duration */
X 11.0, 80.0, 10.0, 125.0, 40,
X /* quickness strength mana energy brains magic lvl */
X 34, 0, 0.0, 20, 6, 2.0, 25,21,30.0, 55,36,30.0, 40,36, 4.5, 1, 4, 1.0,
X
X /* EXPERIMENTO */
X /* max brains, max mana, weakness, gold tote, ring duration */
X 9.0, 90.0, 16.0, 160.0, 20,
X /* quickness strength mana energy brains magic lvl */
X 27, 0, 0.0, 25, 0, 0.0, 100,0, 0.0, 35, 0, 0.0, 25, 0, 0.0, 2, 0, 0.0,
X
X /* SUPER */
X /* max brains, max mana, weakness, gold tote, ring duration */
X 15.0, 200.0, 10.0, 225.0, 40,
X /* quickness strength mana energy brains magic lvl */
X 38, 0, 0.0, 65, 0, 5.0, 100,0,75.0, 80, 0,35.0, 85, 0, 6.0, 9, 0,2.75
X };
X
X/* menu of items for purchase */
Xstruct menuitem Menu[] =
X {
X "Mana", 1,
X "Shield", 5,
X "Book", 200,
X "Sword", 500,
X "Charm", 1000,
X "Quicksilver", 2500,
X "Blessing", 1000,
X };
X
XFILE *Playersfp; /* pointer to open player file */
XFILE *Monstfp; /* pointer to open monster file */
XFILE *Messagefp; /* pointer to open message file */
XFILE *Energyvoidfp; /* pointer to open energy void file */
X
Xchar Databuf[SZ_DATABUF]; /* a place to read data into */
X
X/* edit these path definitions to let files reside elsewhere */
Xchar Monstfile[] = DEST/monsters"; /* monster database */
Xchar Peoplefile[] = DEST/characs"; /* player database */
Xchar Gameprog[] = DEST/phantasia"; /* game binary */
Xchar Messfile[] = DEST/mess"; /* player to player messages */
Xchar Lastdead[] = DEST/lastdead"; /* data on last player killed */
Xchar Helpfile[] = DEST/phant.help"; /* manual pages */
Xchar Motdfile[] = DEST/motd"; /* message from 'wizard' */
Xchar Goldfile[] = DEST/gold"; /* gold collected in taxes */
Xchar Voidfile[] = DEST/void"; /* energy void database */
Xchar Scorefile[] = DEST/scoreboard"; /* hi score database */
X#ifdef ENEMY
Xchar Enemyfile[] = DEST/enemy"; /* restricted account database */
X#endif
X
X/* some canned strings for messages */
Xchar Illcmd[] = "Illegal command.\n";
Xchar Illmove[] = "Too far.\n";
Xchar Illspell[] = "Illegal spell.\n";
Xchar Nomana[] = "Not enought mana for that spell.\n";
Xchar Somebetter[] = "But you already have something better.\n";
Xchar Nobetter[] = "That's no better than what you already have.\n";
!EOR!
echo x - fight.c
sed 's/^X//' > fight.c << '!EOR!'
X/*
X * fight.c Phantasia monster fighting routines
X */
X
X#include "include.h"
X
X/************************************************************************
X/
X/ FUNCTION NAME: encounter()
X/
X/ FUNCTION: monster battle routine
X/
X/ AUTHOR: E. A. Estes, 2/20/86
X/
X/ ARGUMENTS:
X/ int particular - particular monster to fight if >= 0
X/
X/ RETURN VALUE: none
X/
X/ MODULES CALLED: monsthits(), playerhits(), readmessage(), callmonster(),
X/ writerecord(), pickmonster(), displaystats(), pow(), cancelmonster(),
X/ awardtreasure(), more(), death(), wmove(), setjmp(), random(), printw(),
X/ longjmp(), wrefresh(), mvprintw(), wclrtobot()
X/
X/ GLOBAL INPUTS: Curmonster, Whichmonster, LINES, Lines, Circle, Shield,
X/ Player, *stdscr, Fileloc, Fightenv[], *Enemyname
X/
X/ GLOBAL OUTPUTS: Curmonster, Whichmonster, Lines, Shield, Player, Luckout
X/
X/ DESCRIPTION:
X/ Choose a monster and check against some special types.
X/ Arbitrate between monster and player. Watch for either
X/ dying.
X/
X/************************************************************************/
X
Xencounter(particular)
Xint particular;
X{
Xbool firsthit = Player.p_blessing; /* set if player gets the first hit */
Xint howmany = 1; /* how many time flocked */
X
X /* let others know what we are doing */
X Player.p_status = S_MONSTER;
X writerecord(&Player, Fileloc);
X
X#ifdef SYS5
X flushinp();
X#endif
X
X Shield = 0.0; /* no shield up yet */
X
X if (particular >= 0)
X /* monster is specified */
X Whichmonster = particular;
X else
X /* pick random monster */
X Whichmonster = pickmonster();
X
X setjmp(Fightenv); /* this is to enable changing fight state */
X
X move(6, 0);
X clrtobot(); /* clear bottom area of screen */
X
X Lines = 9;
X callmonster(Whichmonster); /* set up monster to fight */
X
X Luckout = FALSE; /* haven't tried to luckout yet */
X
X if (Curmonster.m_type == SM_MORGOTH)
X mvprintw(4, 0, "You've encountered %s, Bane of the Council and Valar.\n",
X Enemyname);
X
X if (Curmonster.m_type == SM_UNICORN)
X {
X if (Player.p_virgin)
X {
X printw("You just subdued %s, thanks to the virgin.\n", Enemyname);
X Player.p_virgin = FALSE;
X }
X else
X {
X printw("You just saw %s running away!\n", Enemyname);
X Curmonster.m_experience = 0.0;
X Curmonster.m_treasuretype = 0;
X }
X }
X else
X /* not a special monster */
X for (;;)
X /* print header, and arbitrate between player and monster */
X {
X mvprintw(6, 0, "You are being attacked by %s, EXP: %.0f (Size: %.0f)\n",
X Enemyname, Curmonster.m_experience, Circle);
X
X displaystats();
X mvprintw(1, 26, "%20.0f", Player.p_energy + Shield); /* overprint energy */
X readmessage();
X
X if (Curmonster.m_type == SM_DARKLORD
X && Player.p_blessing
X && Player.p_charms > 0)
X /* overpower Dark Lord with blessing and charm */
X {
X mvprintw(7, 0, "You just overpowered %s!", Enemyname);
X Lines = 8;
X Player.p_blessing = FALSE;
X --Player.p_charms;
X break;
X }
X
X /* allow paralyzed monster to wake up */
X Curmonster.m_speed = MIN(Curmonster.m_speed + 1.0, Curmonster.m_maxspeed);
X
X if (random() * Curmonster.m_speed > random() * Player.p_speed
X /* monster is faster */
X && Curmonster.m_type != SM_DARKLORD
X /* not D. L. */
X && Curmonster.m_type != SM_SHRIEKER
X /* not mimic */
X && !firsthit)
X /* monster gets a hit */
X monsthits();
X else
X /* player gets a hit */
X {
X firsthit = FALSE;
X playerhits();
X }
X
X refresh();
X
X if (Lines > LINES - 2)
X /* near bottom of screen - pause */
X {
X more(Lines);
X move(Lines = 8, 0);
X clrtobot();
X }
X
X if (Player.p_energy <= 0.0)
X /* player died */
X {
X more(Lines);
X death(Enemyname);
X cancelmonster();
X break; /* fight ends if the player is saved from death */
X }
X
X if (Curmonster.m_energy <= 0.0)
X /* monster died */
X break;
X }
X
X /* give player credit for killing monster */
X Player.p_experience += Curmonster.m_experience;
X
X if (random() < Curmonster.m_flock / 100.0)
X /* monster flocks */
X {
X more(Lines);
X ++howmany;
X longjmp(Fightenv, 0);
X /*NOTREACHED*/
X }
X else if (Circle > 1.0
X && Curmonster.m_treasuretype > 0
X && random() > 0.2 + pow(0.4, (double) (howmany / 3 + Circle / 3.0)))
X /* monster has treasure; this takes # of flocks and size into account */
X {
X more(Lines);
X awardtreasure();
X }
X
X /* pause before returning */
X getyx(stdscr, Lines, howmany);
X more(Lines + 1);
X
X Player.p_ring.ring_inuse = FALSE; /* not using ring */
X
X /* clean up the screen */
X move(4, 0);
X clrtobot();
X}
X/**/
X/************************************************************************
X/
X/ FUNCTION NAME: pickmonster()
X/
X/ FUNCTION: choose a monster based upon where we are
X/
X/ AUTHOR: E. A. Estes, 2/20/86
X/
X/ ARGUMENTS: none
X/
X/ RETURN VALUE: monster number to call
X/
X/ MODULES CALLED: floor(), random()
X/
X/ GLOBAL INPUTS: Marsh, Circle, Player
X/
X/ GLOBAL OUTPUTS: none
X/
X/ DESCRIPTION:
X/ Certain monsters can be found in certain areas of the grid.
X/ We take care of rolling them here.
X/ Unfortunately, this routine assumes that the monster data
X/ base is arranged in a particular order. If the data base
X/ is altered (to add monsters, or make them tougher), this
X/ routine may also need to be changed.
X/
X/************************************************************************/
X
Xpickmonster()
X{
X if (Player.p_specialtype == SC_VALAR)
X /* even chance of any monster */
X return((int) ROLL(0.0, 100.0));
X
X if (Marsh)
X /* water monsters */
X return((int) ROLL(0.0, 15.0));
X
X else if (Circle > 24)
X /* even chance of all non-water monsters */
X return((int) ROLL(14.0, 86.0));
X
X else if (Circle > 15)
X /* chance of all non-water monsters, weighted toward middle */
X return((int) (ROLL(0.0, 50.0) + ROLL(14.0, 37.0)));
X
X else if (Circle > 8)
X /* not all non-water monsters, weighted toward middle */
X return((int) (ROLL(0.0, 50.0) + ROLL(14.0, 26.0)));
X
X else if (Circle > 3)
X /* even chance of some tamer non-water monsters */
X return((int) ROLL(14.0, 50.0));
X
X else
X /* even chance of some of the tamest non-water monsters */
X return((int) ROLL(14.0, 25.0));
X}
X/**/
X/************************************************************************
X/
X/ FUNCTION NAME: playerhits()
X/
X/ FUNCTION: prompt player for action in monster battle, and process
X/
X/ AUTHOR: E. A. Estes, 12/4/85
X/
X/ ARGUMENTS: none
X/
X/ RETURN VALUE: none
X/
X/ MODULES CALLED: hitmonster(), throwspell(), inputoption(), cancelmonster(),
X/ floor(), wmove(), random(), altercoordinates(), waddstr(), mvprintw(),
X/ wclrtoeol(), wclrtobot()
X/
X/ GLOBAL INPUTS: Curmonster, Lines, Player, *stdscr, Luckout, *Enemyname
X/
X/ GLOBAL OUTPUTS: Curmonster, Lines, Player, Luckout
X/
X/ DESCRIPTION:
X/ Process all monster battle options.
X/
X/************************************************************************/
X
Xplayerhits()
X{
Xdouble inflict; /* damage inflicted */
Xint ch; /* input */
X
X mvaddstr(7, 0, "1:Melee 2:Skirmish 3:Evade 4:Spell 5:Nick ");
X
X if (!Luckout)
X /* haven't tried to luckout yet */
X if (Curmonster.m_type == SM_MORGOTH)
X /* cannot luckout against Morgoth */
X addstr("6:Ally ");
X else
X addstr("6:Luckout ");
X
X if (Player.p_ring.ring_type != R_NONE)
X /* player has a ring */
X addstr("7:Use Ring ");
X else
X clrtoeol();
X
X ch = inputoption();
X
X move(8, 0);
X clrtobot(); /* clear any messages from before */
X Lines = 9;
X mvaddstr(4, 0, "\n\n"); /* clear status area */
X
X switch (ch)
X {
X case 'T': /* timeout; lose turn */
X break;
X
X case ' ':
X case '1': /* melee */
X /* melee affects monster's energy and strength */
X inflict = ROLL(Player.p_might / 2.0 + 5.0, 1.3 * Player.p_might)
X + (Player.p_ring.ring_inuse ? Player.p_might : 0.0);
X
X Curmonster.m_melee += inflict;
X Curmonster.m_strength = Curmonster.m_o_strength
X - Curmonster.m_melee / Curmonster.m_o_energy
X * Curmonster.m_o_strength / 4.0;
X hitmonster(inflict);
X break;
X
X case '2': /* skirmish */
X /* skirmish affects monter's energy and speed */
X inflict = ROLL(Player.p_might / 3.0 + 3.0, 1.1 * Player.p_might)
X + (Player.p_ring.ring_inuse ? Player.p_might : 0.0);
X
X Curmonster.m_skirmish += inflict;
X Curmonster.m_maxspeed = Curmonster.m_o_speed
X - Curmonster.m_skirmish / Curmonster.m_o_energy
X * Curmonster.m_o_speed / 4.0;
X hitmonster(inflict);
X break;
X
X case '3': /* evade */
X /* use brains and speed to try to evade */
X if ((Curmonster.m_type == SM_DARKLORD
X || Curmonster.m_type == SM_SHRIEKER
X /* can always run from D. L. and shrieker */
X || random() * Player.p_speed * Player.p_brains
X > random() * Curmonster.m_speed * Curmonster.m_brains)
X && (Curmonster.m_type != SM_MIMIC))
X /* cannot run from mimic */
X {
X mvaddstr(Lines++, 0, "You got away!");
X cancelmonster();
X altercoordinates(0.0, 0.0, A_NEAR);
X }
X else
X mvprintw(Lines++, 0, "%s is still after you!", Enemyname);
X
X break;
X
X case 'M':
X case '4': /* magic spell */
X throwspell();
X break;
X
X case '5': /* nick */
X /* hit 1 plus sword; give some experience */
X inflict = 1.0 + Player.p_sword;
X Player.p_experience += floor(Curmonster.m_experience / 10.0);
X Curmonster.m_experience *= 0.92;
X /* monster gets meaner */
X Curmonster.m_maxspeed += 2.0;
X Curmonster.m_speed = (Curmonster.m_speed < 0.0) ? 0.0 : Curmonster.m_speed + 2.0;
X if (Curmonster.m_type == SM_DARKLORD)
X /* Dark Lord; doesn't like to be nicked */
X {
X mvprintw(Lines++, 0,
X "You hit %s %.0f times, and made him mad!", Enemyname, inflict);
X Player.p_quickness /= 2.0;
X altercoordinates(0.0, 0.0, A_FAR);
X cancelmonster();
X }
X else
X hitmonster(inflict);
X break;
X
X case 'B':
X case '6': /* luckout */
X if (Luckout)
X mvaddstr(Lines++, 0, "You already tried that.");
X else
X {
X Luckout = TRUE;
X if (Curmonster.m_type == SM_MORGOTH)
X /* Morgoth; ally */
X {
X if (random() < Player.p_sin / 100.0)
X {
X mvprintw(Lines++, 0, "%s accepted!", Enemyname);
X cancelmonster();
X }
X else
X mvaddstr(Lines++, 0, "Nope, he's not interested.");
X }
X else
X /* normal monster; use brains for success */
X {
X if ((random() + 0.333) * Player.p_brains
X < (random() + 0.333) * Curmonster.m_brains)
X mvprintw(Lines++, 0, "You blew it, %s.", Player.p_name);
X else
X {
X mvaddstr(Lines++, 0, "You made it!");
X Curmonster.m_energy = 0.0;
X }
X }
X }
X break;
X
X case '7': /* use ring */
X if (Player.p_ring.ring_type != R_NONE)
X {
X mvaddstr(Lines++, 0, "Now using ring.");
X Player.p_ring.ring_inuse = TRUE;
X if (Player.p_ring.ring_type != R_DLREG)
X /* age ring */
X --Player.p_ring.ring_duration;
X }
X break;
X }
X
X}
X/**/
X/************************************************************************
X/
X/ FUNCTION NAME: monsthits()
X/
X/ FUNCTION: process a monster hitting the player
X/
X/ AUTHOR: E. A. Estes, 12/4/85
X/
X/ ARGUMENTS: none
X/
X/ RETURN VALUE: none
X/
X/ MODULES CALLED: cancelmonster(), scramblestats(), more(), floor(), wmove(),
X/ random(), altercoordinates(), longjmp(), waddstr(), mvprintw(),
X/ getanswer()
X/
X/ GLOBAL INPUTS: Curmonster, Lines, Circle, Shield, Player, *stdscr,
X/ Fightenv[], *Enemyname
X/
X/ GLOBAL OUTPUTS: Curmonster, Whichmonster, Lines, Shield, Player,
X/ *Enemyname
X/
X/ DESCRIPTION:
X/ Handle all special monsters here. If the monster is not a special
X/ one, simply roll a hit against the player.
X/
X/************************************************************************/
X
Xmonsthits()
X{
Xdouble inflict; /* damage inflicted */
Xint ch; /* input */
X
X switch (Curmonster.m_type)
X /* may be a special monster */
X {
X case SM_DARKLORD:
X /* hits just enough to kill player */
X inflict = (Player.p_energy + Shield) * 1.02;
X goto SPECIALHIT;
X
X case SM_SHRIEKER:
X /* call a big monster */
X mvaddstr(Lines++, 0,
X "Shrieeeek!! You scared it, and it called one of its friends.");
X more(Lines);
X Whichmonster = (int) ROLL(70.0, 30.0);
X longjmp(Fightenv, 0);
X /*NOTREACHED*/
X
X case SM_BALROG:
X /* take experience away */
X inflict = ROLL(10.0, Curmonster.m_strength);
X inflict = MIN(Player.p_experience, inflict);
X mvprintw(Lines++, 0,
X "%s took away %.0f experience points.", Enemyname, inflict);
X Player.p_experience -= inflict;
X return;
X
X case SM_FAERIES:
X if (Player.p_holywater > 0)
X /* holy water kills when monster tries to hit */
X {
X mvprintw(Lines++, 0, "Your holy water killed it!");
X --Player.p_holywater;
X Curmonster.m_energy = 0.0;
X return;
X }
X break;
X
X case SM_NONE:
X /* normal hit */
X break;
X
X default:
X if (random() > 0.2)
X /* normal hit */
X break;
X
X /* else special things */
X switch (Curmonster.m_type)
X {
X case SM_LEANAN:
X /* takes some of the player's strength */
X inflict = ROLL(1.0, (Circle - 1.0) / 2.0);
X inflict = MIN(Player.p_strength, inflict);
X mvprintw(Lines++, 0, "%s sapped %0.f of your strength!",
X Enemyname, inflict);
X Player.p_strength -= inflict;
X Player.p_might -= inflict;
X break;
X
X case SM_SARUMAN:
X if (Player.p_palantir)
X /* take away palantir */
X {
X mvprintw(Lines++, 0, "Wormtongue stole your palantir!");
X Player.p_palantir = FALSE;
X }
X else if (random() > 0.5)
X /* gems turn to gold */
X {
X mvprintw(Lines++, 0,
X "%s transformed your gems into gold!", Enemyname);
X Player.p_gold += Player.p_gems;
X Player.p_gems = 0.0;
X }
X else
X /* scramble some stats */
X {
X mvprintw(Lines++, 0, "%s scrambled your stats!", Enemyname);
X scramblestats();
X }
X break;
X
X case SM_THAUMATURG:
X /* transport player */
X mvprintw(Lines++, 0, "%s transported you!", Enemyname);
X altercoordinates(0.0, 0.0, A_FAR);
X cancelmonster();
X break;
X
X case SM_VORTEX:
X /* suck up some mana */
X inflict = ROLL(0, 7.5 * Circle);
X inflict = MIN(Player.p_mana, floor(inflict));
X mvprintw(Lines++, 0,
X "%s sucked up %.0f of your mana!", Enemyname, inflict);
X Player.p_mana -= inflict;
X break;
X
X case SM_NAZGUL:
X /* try to take ring if player has one */
X if (Player.p_ring.ring_type != R_NONE)
X /* player has a ring */
X {
X mvaddstr(Lines++, 0, "Will you relinguish your ring ? ");
X ch = getanswer("YN", FALSE);
X if (ch == 'Y')
X /* take ring away */
X {
X Player.p_ring.ring_type = R_NONE;
X Player.p_ring.ring_inuse = FALSE;
X cancelmonster();
X break;
X }
X }
X
X /* otherwise, take some brains */
X mvprintw(Lines++, 0,
X "%s neutralized 1/5 of your brain!", Enemyname);
X Player.p_brains *= 0.8;
X break;
X
X case SM_TIAMAT:
X /* take some gold and gems */
X mvprintw(Lines++, 0,
X "%s took half your gold and gems and flew off.", Enemyname);
X Player.p_gold /= 2.0;
X Player.p_gems /= 2.0;
X cancelmonster();
X break;
X
X case SM_KOBOLD:
X /* steal a gold piece and run */
X mvprintw(Lines++, 0,
X "%s stole one gold piece and ran away.", Enemyname);
X Player.p_gold = MAX(0.0, Player.p_gold - 1.0);
X cancelmonster();
X break;
X
X case SM_SHELOB:
X /* bite and (medium) poison */
X mvprintw(Lines++, 0,
X "%s has bitten and poisoned you!", Enemyname);
X Player.p_poison -= 1.0;
X break;
X
X case SM_LAMPREY:
X /* bite and (small) poison */
X mvprintw(Lines++, 0, "%s bit and poisoned you!", Enemyname);
X Player.p_poison += 0.25;
X break;
X
X case SM_BONNACON:
X /* fart and run */
X mvprintw(Lines++, 0, "%s farted and scampered off.", Enemyname);
X Player.p_energy /= 2.0; /* damage from fumes */
X cancelmonster();
X break;
X
X case SM_SMEAGOL:
X if (Player.p_ring.ring_type != R_NONE)
X /* try to steal ring */
X {
X mvprintw(Lines++, 0,
X "%s tried to steal your ring, ", Enemyname);
X if (random() > 0.1)
X addstr("but was unsuccessful.");
X else
X {
X addstr("and ran away with it!");
X Player.p_ring.ring_type = R_NONE;
X cancelmonster();
X }
X }
X break;
X
X case SM_SUCCUBUS:
X /* inflict damage through shield */
X inflict = ROLL(15.0, Circle * 10.0);
X inflict = MIN(inflict, Player.p_energy);
X mvprintw(Lines++, 0, "%s sapped %.0f of your energy.",
X Enemyname, inflict);
X Player.p_energy -= inflict;
X break;
X
X case SM_CERBERUS:
X /* take all metal treasures */
X mvprintw(Lines++, 0,
X "%s took all your metal treasures!", Enemyname);
X Player.p_crowns = 0;
X Player.p_sword =
X Player.p_shield =
X Player.p_gold = 0.0;
X cancelmonster();
X break;
X
X case SM_UNGOLIANT:
X /* (large) poison and take a quickness */
X mvprintw(Lines++, 0,
X "%s poisoned you, and took one quik.", Enemyname);
X Player.p_poison += 5.0;
X Player.p_quickness -= 1.0;
X break;
X
X case SM_JABBERWOCK:
X /* fly away, and leave either a Jubjub bird or Bonnacon */
X mvprintw(Lines++, 0,
X "%s flew away, and left you to contend with one of its friends.",
X Enemyname);
X Whichmonster = 55 + (random() > 0.5) ? 22 : 0;
X longjmp(Fightenv, 0);
X /*NOTREACHED*/
X
X case SM_TROLL:
X /* partially regenerate monster */
X mvprintw(Lines++, 0,
X "%s partially regenerated his energy.!", Enemyname);
X Curmonster.m_energy +=
X floor((Curmonster.m_o_energy - Curmonster.m_energy) / 2.0);
X Curmonster.m_strength = Curmonster.m_o_strength;
X Curmonster.m_melee = Curmonster.m_skirmish = 0.0;
X Curmonster.m_maxspeed = Curmonster.m_o_speed;
X break;
X
X case SM_WRAITH:
X if (!Player.p_blindness)
X /* make blind */
X {
X mvprintw(Lines++, 0, "%s blinded you!", Enemyname);
X Player.p_blindness = TRUE;
X Enemyname = "A monster";
X }
X break;
X }
X return;
X }
X
X /* fall through to here if monster inflicts a normal hit */
X inflict = random() * Curmonster.m_strength + 0.5;
XSPECIALHIT:
X mvprintw(Lines++, 0, "%s hit you %.0f times!", Enemyname, inflict);
X
X if ((Shield -= inflict) < 0)
X {
X Player.p_energy += Shield;
X Shield = 0.0;
X }
X}
X/**/
X/************************************************************************
X/
X/ FUNCTION NAME: cancelmonster()
X/
X/ FUNCTION: mark current monster as no longer active
X/
X/ AUTHOR: E. A. Estes, 12/4/85
X/
X/ ARGUMENTS: none
X/
X/ RETURN VALUE: none
X/
X/ MODULES CALLED: none
X/
X/ GLOBAL INPUTS: none
X/
X/ GLOBAL OUTPUTS: Curmonster
X/
X/ DESCRIPTION:
X/ Clear current monster's energy, experience, treasure type, and
X/ flock. This is the same as having the monster run away.
X/
X/************************************************************************/
X
Xcancelmonster()
X{
X Curmonster.m_energy = 0.0;
X Curmonster.m_experience = 0.0;
X Curmonster.m_treasuretype = 0;
X Curmonster.m_flock = 0.0;
X}
X/**/
X/************************************************************************
X/
X/ FUNCTION NAME: hitmonster()
X/
X/ FUNCTION: inflict damage upon current monster
X/
X/ AUTHOR: E. A. Estes, 12/4/85
X/
X/ ARGUMENTS:
X/ double inflict - damage to inflict upon monster
X/
X/ RETURN VALUE: none
X/
X/ MODULES CALLED: monsthits(), wmove(), strcmp(), waddstr(), mvprintw()
X/
X/ GLOBAL INPUTS: Curmonster, Lines, Player, *stdscr, *Enemyname
X/
X/ GLOBAL OUTPUTS: Curmonster, Lines
X/
X/ DESCRIPTION:
X/ Hit monster specified number of times. Handle when monster dies,
X/ and a few special monsters.
X/
X/************************************************************************/
X
Xhitmonster(inflict)
Xdouble inflict;
X{
X mvprintw(Lines++, 0, "You hit %s %.0f times!", Enemyname, inflict);
X Curmonster.m_energy -= inflict;
X if (Curmonster.m_energy > 0.0)
X {
X if (Curmonster.m_type == SM_DARKLORD || Curmonster.m_type == SM_SHRIEKER)
X /* special monster didn't die */
X monsthits();
X }
X else
X /* monster died. print message. */
X {
X if (Curmonster.m_type == SM_MORGOTH)
X mvaddstr(Lines++, 0, "You have defeated Morgoth, but he may return. . .");
X else
X /* all other types of monsters */
X {
X mvprintw(Lines++, 0, "You killed it. Good work, %s.", Player.p_name);
X
X if (Curmonster.m_type == SM_MIMIC
X && strcmp(Curmonster.m_name, "A Mimic") != 0
X && !Player.p_blindness)
X mvaddstr(Lines++, 0, "The body slowly changes into the form of a mimic.");
X }
X }
X}
X/**/
X/************************************************************************
X/
X/ FUNCTION NAME: throwspell()
X/
X/ FUNCTION: throw a magic spell
X/
X/ AUTHOR: E. A. Estes, 12/4/85
X/
X/ ARGUMENTS: none
X/
X/ RETURN VALUE: none
X/
X/ MODULES CALLED: hitmonster(), cancelmonster(), sqrt(), floor(), wmove(),
X/ random(), altercoordinates(), longjmp(), infloat(), waddstr(), mvprintw(),
X/ getanswer()
X/
X/ GLOBAL INPUTS: Curmonster, Whichmonster, Nomana[], Player, *stdscr,
X/ Fightenv[], Illspell[], *Enemyname
X/
X/ GLOBAL OUTPUTS: Curmonster, Whichmonster, Shield, Player
X/
X/ DESCRIPTION:
X/ Prompt player and process magic spells.
X/
X/************************************************************************/
X
Xthrowspell()
X{
Xdouble inflict; /* damage inflicted */
Xdouble dtemp; /* for dtemporary calculations */
Xint ch; /* input */
X
X mvaddstr(7, 0, "\n\n"); /* clear menu area */
X
X if (Player.p_magiclvl >= ML_ALLORNOTHING)
X mvaddstr(7, 0, "1:All or Nothing ");
X if (Player.p_magiclvl >= ML_MAGICBOLT)
X addstr("2:Magic Bolt ");
X if (Player.p_magiclvl >= ML_FORCEFIELD)
X addstr("3:Force Field ");
X if (Player.p_magiclvl >= ML_XFORM)
X addstr("4:Transform ");
X if (Player.p_magiclvl >= ML_INCRMIGHT)
X addstr("5:Increase Might\n");
X if (Player.p_magiclvl >= ML_INVISIBLE)
X mvaddstr(8, 0, "6:Invisibility ");
X if (Player.p_magiclvl >= ML_XPORT)
X addstr("7:Transport ");
X if (Player.p_magiclvl >= ML_PARALYZE)
X addstr("8:Paralyze ");
X if (Player.p_specialtype >= SC_COUNCIL)
X addstr("9:Specify");
X mvaddstr(4, 0, "Spell ? ");
X
X ch = getanswer(" ", TRUE);
X
X mvaddstr(7, 0, "\n\n"); /* clear menu area */
X
X if (Curmonster.m_type == SM_MORGOTH && ch != '3')
X /* can only throw force field against Morgoth */
X ILLSPELL();
X else
X switch (ch)
X {
X case '1': /* all or nothing */
X if (random() < 0.25)
X /* success */
X {
X inflict = Curmonster.m_energy * 1.01 + 1.0;
X
X if (Curmonster.m_type == SM_DARKLORD)
X /* all or nothing doesn't quite work against D. L. */
X inflict *= 0.9;
X }
X else
X /* failure -- monster gets stronger and quicker */
X {
X Curmonster.m_o_strength = Curmonster.m_strength *= 2.0;
X Curmonster.m_maxspeed *= 2.0;
X Curmonster.m_o_speed *= 2.0;
X
X /* paralyzed monsters wake up a bit */
X Curmonster.m_speed = MAX(1.0, Curmonster.m_speed * 2.0);
X }
X
X if (Player.p_mana >= MM_ALLORNOTHING)
X /* take a mana if player has one */
X Player.p_mana -= MM_ALLORNOTHING;
X
X hitmonster(inflict);
X break;
X
X case '2': /* magic bolt */
X if (Player.p_magiclvl < ML_MAGICBOLT)
X ILLSPELL();
X else
X {
X do
X /* prompt for amount to expend */
X {
X mvaddstr(4, 0, "How much mana for bolt? ");
X dtemp = floor(infloat());
X }
X while (dtemp < 0.0 || dtemp > Player.p_mana);
X
X Player.p_mana -= dtemp;
X
X if (Curmonster.m_type == SM_DARKLORD)
X /* magic bolts don't work against D. L. */
X inflict = 0.0;
X else
X inflict = dtemp * ROLL(15.0, sqrt(Player.p_magiclvl / 3.0 + 1.0));
X mvaddstr(5, 0, "Magic Bolt fired!\n");
X hitmonster(inflict);
X }
X break;
X
X case '3': /* force field */
X if (Player.p_magiclvl < ML_FORCEFIELD)
X ILLSPELL();
X else if (Player.p_mana < MM_FORCEFIELD)
X NOMANA();
X else
X {
X Player.p_mana -= MM_FORCEFIELD;
X Shield = (Player.p_maxenergy + Player.p_shield) * 4.2 + 45.0;
X mvaddstr(5, 0, "Force Field up.\n");
X }
X break;
X
X case '4': /* transform */
X if (Player.p_magiclvl < ML_XFORM)
X ILLSPELL();
X else if (Player.p_mana < MM_XFORM)
X NOMANA();
X else
X {
X Player.p_mana -= MM_XFORM;
X Whichmonster = (int) ROLL(0.0, 100.0);
X longjmp(Fightenv, 0);
X /*NOTREACHED*/
X }
X break;
X
X case '5': /* increase might */
X if (Player.p_magiclvl < ML_INCRMIGHT)
X ILLSPELL();
X else if (Player.p_mana < MM_INCRMIGHT)
X NOMANA();
X else
X {
X Player.p_mana -= MM_INCRMIGHT;
X Player.p_might +=
X (1.2 * (Player.p_strength + Player.p_sword)
X + 5.0 - Player.p_might) / 2.0;
X mvprintw(5, 0, "New strength: %.0f\n", Player.p_might);
X }
X break;
X
X case '6': /* invisible */
X if (Player.p_magiclvl < ML_INVISIBLE)
X ILLSPELL();
X else if (Player.p_mana < MM_INVISIBLE)
X NOMANA();
X else
X {
X Player.p_mana -= MM_INVISIBLE;
X Player.p_speed +=
X (1.2 * (Player.p_quickness + Player.p_quksilver)
X + 5.0 - Player.p_speed) / 2.0;
X mvprintw(5, 0, "New quickness: %.0f\n", Player.p_speed);
X }
X break;
X
X case '7': /* transport */
X if (Player.p_magiclvl < ML_XPORT)
X ILLSPELL();
X else if (Player.p_mana < MM_XPORT)
X NOMANA();
X else
X {
X Player.p_mana -= MM_XPORT;
X if (Player.p_brains + Player.p_magiclvl
X < Curmonster.m_experience / 200.0 * random())
X {
X mvaddstr(5, 0, "Transport backfired!\n");
X altercoordinates(0.0, 0.0, A_FAR);
X cancelmonster();
X }
X else
X {
X mvprintw(5, 0, "%s is transported.\n", Enemyname);
X if (random() < 0.3)
X /* monster didn't drop its treasure */
X Curmonster.m_treasuretype = 0;
X
X Curmonster.m_energy = 0.0;
X }
X }
X break;
X
X case '8': /* paralyze */
X if (Player.p_magiclvl < ML_PARALYZE)
X ILLSPELL();
X else if (Player.p_mana < MM_PARALYZE)
X NOMANA();
X else
X {
X Player.p_mana -= MM_PARALYZE;
X if (Player.p_magiclvl >
X Curmonster.m_experience / 1000.0 * random())
X {
X mvprintw(5, 0, "%s is held.\n", Enemyname);
X Curmonster.m_speed = -2.0;
X }
X else
X mvaddstr(5, 0, "Monster unaffected.\n");
X }
X break;
X
X case '9': /* specify */
X if (Player.p_specialtype < SC_COUNCIL)
X ILLSPELL();
X else if (Player.p_mana < MM_SPECIFY)
X NOMANA();
X else
X {
X Player.p_mana -= MM_SPECIFY;
X mvaddstr(5, 0, "Which monster do you want [0-99] ? ");
X Whichmonster = (int) infloat();
X Whichmonster = MAX(0, MIN(99, Whichmonster));
X longjmp(Fightenv, 0);
X /*NOTREACHED*/
X }
X break;
X }
X}
X/**/
X/************************************************************************
X/
X/ FUNCTION NAME: callmonster()
X/
X/ FUNCTION: read monster from file, and fill structure
X/
X/ AUTHOR: E. A. Estes, 2/25/86
X/
X/ ARGUMENTS:
X/ int which - which monster to call
X/
X/ RETURN VALUE: none
X/
X/ MODULES CALLED: truncstring(), fread(), fseek(), floor(), random(),
X/ strcpy()
X/
X/ GLOBAL INPUTS: Curmonster, Circle, Player, *Monstfp
X/
X/ GLOBAL OUTPUTS: Curmonster, Player, *Enemyname
X/
X/ DESCRIPTION:
X/ Read specified monster from monster database and fill up
X/ current monster structure.
X/ Adjust statistics based upon current size.
X/ Handle some special monsters.
X/
X/************************************************************************/
X
Xcallmonster(which)
Xint which;
X{
Xstruct monster Othermonster; /* to find a name for mimics */
X
X which = MIN(which, 99); /* make sure within range */
X
X /* fill structure */
X fseek(Monstfp, (long) which * (long) SZ_MONSTERSTRUCT, 0);
X fread((char *) &Curmonster, SZ_MONSTERSTRUCT, 1, Monstfp);
X
X /* handle some special monsters */
X if (Curmonster.m_type == SM_MODNAR)
X {
X if (Player.p_specialtype < SC_COUNCIL)
X /* randomize some stats */
X {
X Curmonster.m_strength *= random() + 0.5;
X Curmonster.m_brains *= random() + 0.5;
X Curmonster.m_speed *= random() + 0.5;
X Curmonster.m_energy *= random() + 0.5;
X Curmonster.m_experience *= random() + 0.5;
X Curmonster.m_treasuretype =
X (int) ROLL(0.0, (double) Curmonster.m_treasuretype);
X }
X else
X /* make Modnar into Morgoth */
X {
X strcpy(Curmonster.m_name, "Morgoth");
X Curmonster.m_strength = random() * (Player.p_maxenergy + Player.p_shield) / 1.4
X + random() * (Player.p_maxenergy + Player.p_shield) / 1.5;
X Curmonster.m_brains = Player.p_brains;
X Curmonster.m_energy = Player.p_might * 30.0;
X Curmonster.m_type = SM_MORGOTH;
X Curmonster.m_speed = Player.p_speed * 1.1
X + (Player.p_specialtype == SC_EXVALAR) ? Player.p_speed : 0.0;
X Curmonster.m_flock = 0.0;
X Curmonster.m_treasuretype = 0;
X Curmonster.m_experience = 0.0;
X }
X }
X else if (Curmonster.m_type == SM_MIMIC)
X /* pick another name */
X {
X which = (int) ROLL(0.0, 100.0);
X fseek(Monstfp, (long) which * (long) SZ_MONSTERSTRUCT, 0);
X fread(&Othermonster, SZ_MONSTERSTRUCT, 1, Monstfp);
X strcpy(Curmonster.m_name, Othermonster.m_name);
X }
X
X truncstring(Curmonster.m_name);
X
X if (Curmonster.m_type != SM_MORGOTH)
X /* adjust stats based on which circle player is in */
X {
X Curmonster.m_strength *= (1.0 + Circle / 2.0);
X Curmonster.m_brains *= Circle;
X Curmonster.m_speed += Circle * 1.e-9;
X Curmonster.m_energy *= Circle;
X Curmonster.m_experience *= Circle;
X }
X
X if (Player.p_blindness)
X /* cannot see monster if blind */
X Enemyname = "A monster";
X else
X Enemyname = Curmonster.m_name;
X
X if (Player.p_speed <= 0.0)
X /* make Player.p_speed positive */
X {
X Curmonster.m_speed += -Player.p_speed;
X Player.p_speed = 1.0;
X }
X
X /* fill up the rest of the structure */
X Curmonster.m_o_strength = Curmonster.m_strength;
X Curmonster.m_o_speed = Curmonster.m_maxspeed = Curmonster.m_speed;
X Curmonster.m_o_energy = Curmonster.m_energy;
X Curmonster.m_melee = Curmonster.m_skirmish = 0.0;
X}
X/**/
X/************************************************************************
X/
X/ FUNCTION NAME: awardtreasure()
X/
X/ FUNCTION: select a treasure
X/
X/ AUTHOR: E. A. Estes, 12/4/85
X/
X/ ARGUMENTS: none
X/
X/ RETURN VALUE: none
X/
X/ MODULES CALLED: pickmonster(), collecttaxes(), more(), cursedtreasure(),
X/ floor(), wmove(), random(), sscanf(), printw(), altercoordinates(),
X/ longjmp(), infloat(), waddstr(), getanswer(), getstring(), wclrtobot()
X/
X/ GLOBAL INPUTS: Somebetter[], Curmonster, Whichmonster, Circle, Player,
X/ *stdscr, Databuf[], *Statptr, Fightenv[]
X/
X/ GLOBAL OUTPUTS: Whichmonster, Shield, Player
X/
X/ DESCRIPTION:
X/ Roll up a treasure based upon monster type and size, and
X/ certain player statistics.
X/ Handle cursed treasure.
X/
X/************************************************************************/
X
Xawardtreasure()
X{
Xregister int whichtreasure; /* calculated treasure to grant */
Xint temp; /* temporary */
Xint ch; /* input */
Xdouble treasuretype; /* monster's treasure type */
Xdouble gold = 0.0; /* gold awarded */
Xdouble gems = 0.0; /* gems awarded */
Xdouble dtemp; /* for temporary calculations */
X
X whichtreasure = (int) ROLL(1.0, 3.0); /* pick a treasure */
X treasuretype = (double) Curmonster.m_treasuretype;
X
X move(4, 0);
X clrtobot();
X move(6, 0);
X
X if (random() > 0.65)
X /* gold and gems */
X {
X if (Curmonster.m_treasuretype > 7)
X /* gems */
X {
X gems = ROLL(1.0, (treasuretype - 7.0)
X * (treasuretype - 7.0) * (Circle - 1.0) / 4.0);
X printw("You have discovered %.0f gems!", gems);
X }
X else
X /* gold */
X {
X gold = ROLL(treasuretype * 10.0, treasuretype
X * treasuretype * 10.0 * (Circle - 1.0));
X printw("You have found %.0f gold pieces.", gold);
X }
X
X addstr(" Do you want to pick them up ? ");
X ch = getanswer("NY", FALSE);
X addstr("\n\n");
X
X if (ch == 'Y')
X if (random() < treasuretype / 35.0 + 0.04)
X /* cursed */
X {
X addstr("They were cursed!\n");
X cursedtreasure();
X }
X else
X collecttaxes(gold, gems);
X
X return;
X }
X else
X /* other treasures */
X {
X addstr("You have found some treasure. Do you want to inspect it ? ");
X ch = getanswer("NY", FALSE);
X addstr("\n\n");
X
X if (ch != 'Y')
X return;
X else
X if (random() < 0.08 && Curmonster.m_treasuretype != 4)
X {
X addstr("It was cursed!\n");
X cursedtreasure();
X return;
X }
X else
X switch (Curmonster.m_treasuretype)
X {
X case 1: /* treasure type 1 */
X switch (whichtreasure)
X {
X case 1:
X addstr("You've discovered a power booster!\n");
X Player.p_mana += ROLL(Circle * 4.0, Circle * 30.0);
X break;
X
X case 2:
X addstr("You have encountered a druid.\n");
X Player.p_experience +=
X ROLL(0.0, 2000.0 + Circle * 400.0);
X break;
X
X case 3:
X addstr("You have found a holy orb.\n");
X Player.p_sin = MAX(0.0, Player.p_sin - 0.25);
X break;
X }
X break;
X /* end treasure type 1 */
X
X case 2: /* treasure type 2 */
X switch (whichtreasure)
X {
X case 1:
X addstr("You have found an amulet.\n");
X ++Player.p_amulets;
X break;
X
X case 2:
X addstr("You've found some holy water!\n");
X ++Player.p_holywater;
X break;
X
X case 3:
X addstr("You've met a hermit!\n");
X Player.p_sin *= 0.75;
X Player.p_mana += 12.0 * Circle;
X break;
X }
X break;
X /* end treasure type 2 */
X
X case 3: /* treasure type 3 */
X switch (whichtreasure)
X {
X case 1:
X dtemp = ROLL(7.0, 30.0 + Circle / 10.0);
X printw("You've found a +%.0f shield!\n", dtemp);
X if (dtemp >= Player.p_shield)
X Player.p_shield = dtemp;
X else
X SOMEBETTER();
X break;
X
X case 2:
X addstr("You have rescued a virgin. Will you be honorable ? ");
X ch = getanswer("NY", FALSE);
X addstr("\n\n");
X if (ch == 'Y')
X Player.p_virgin = TRUE;
X else
X {
X Player.p_experience += 2000.0 * Circle;
X ++Player.p_sin;
X }
X break;
X
X case 3:
X addstr("You've discovered some athelas!\n");
X --Player.p_poison;
X break;
X }
X break;
X /* end treasure type 3 */
X
X case 4: /* treasure type 4 */
X addstr("You've found a scroll. Will you read it ? ");
X ch = getanswer("NY", FALSE);
X addstr("\n\n");
X
X if (ch == 'Y')
X switch ((int) ROLL(1, 6))
X {
X case 1:
X addstr("It throws up a shield for you next monster.\n");
X getyx(stdscr, whichtreasure, ch);
X more(whichtreasure);
X Shield =
X (Player.p_maxenergy + Player.p_energy) * 5.5 + Circle * 50.0;
X Whichmonster = pickmonster();
X longjmp(Fightenv, 0);
X /*NOTREACHED*/
X
X case 2:
X addstr("It makes you invisible for you next monster.\n");
X getyx(stdscr, whichtreasure, ch);
X more(whichtreasure);
X Player.p_speed = 1e6;
X Whichmonster = pickmonster();
X longjmp(Fightenv, 0);
X /*NOTREACHED*/
X
X case 3:
X addstr("It increases your strength ten fold to fight your next monster.\n");
X getyx(stdscr, whichtreasure, ch);
X more(whichtreasure);
X Player.p_might *= 10.0;
X Whichmonster = pickmonster();
X longjmp(Fightenv, 0);
X /*NOTREACHED*/
X
X case 4:
X addstr("It is a general knowledge scroll.\n");
X Player.p_brains += ROLL(2.0, Circle);
X Player.p_magiclvl += ROLL(1.0, Circle / 2.0);
X break;
X
X case 5:
X addstr("It tells you how to pick your next monster.\n");
X addstr("Which monster do you want [0-99] ? ");
X Whichmonster = (int) infloat();
X Whichmonster = MIN(99, MAX(0, Whichmonster));
X longjmp(Fightenv, 0);
X
X case 6:
X addstr("It was cursed!\n");
X cursedtreasure();
X break;
X }
X break;
X /* end treasure type 4 */
X
X case 5: /* treasure type 5 */
X switch (whichtreasure)
X {
X case 1:
X dtemp = ROLL(Circle / 4.0 + 5.0, Circle / 2.0 + 9.0);
X printw("You've discovered a +%.0f dagger.\n", dtemp);
X if (dtemp >= Player.p_sword)
X Player.p_sword = dtemp;
X else
X SOMEBETTER();
X break;
X
X case 2:
X dtemp = ROLL(7.5 + Circle * 3.0, Circle * 2.0 + 160.0);
X printw("You have found some +%.0f armour!\n", dtemp);
X if (dtemp >= Player.p_shield)
X Player.p_shield = dtemp;
X else
X SOMEBETTER();
X break;
X
X case 3:
X addstr("You've found a tablet.\n");
X Player.p_brains += 4.5 * Circle;
X break;
X }
X break;
X /* end treasure type 5 */
X
X case 6: /* treasure type 6 */
X switch (whichtreasure)
X {
X case 1:
X addstr("You've found a priest.\n");
X Player.p_energy = Player.p_maxenergy + Player.p_shield;
X Player.p_sin /= 2.0;
X Player.p_mana += 24.0 * Circle;
X Player.p_brains += Circle;
X break;
X
X case 2:
X addstr("You have come upon Robin Hood!\n");
X Player.p_shield += Circle * 2.0;
X Player.p_strength += Circle / 2.5 + 1.0;
X break;
X
X case 3:
X dtemp = ROLL(2.0 + Circle / 4.0, Circle / 1.2 + 10.0);
X printw("You have found a +%.0f axe!\n", dtemp);
X if (dtemp >= Player.p_sword)
X Player.p_sword = dtemp;
X else
X SOMEBETTER();
X break;
X }
X break;
X /* end treasure type 6 */
X
X case 7: /* treasure type 7 */
X switch (whichtreasure)
X {
X case 1:
X addstr("You've discovered a charm!\n");
X ++Player.p_charms;
X break;
X
X case 2:
X addstr("You have encountered Merlyn!\n");
X Player.p_brains += Circle + 5.0;
X Player.p_magiclvl += Circle / 3.0 + 5.0;
X Player.p_mana += Circle * 10.0;
X break;
X
X case 3:
X dtemp = ROLL(5.0 + Circle / 3.0, Circle / 1.5 + 20.0);
X printw("You have found a +%.0f war hammer!\n", dtemp);
X if (dtemp >= Player.p_sword)
X Player.p_sword = dtemp;
X else
X SOMEBETTER();
X break;
X }
X break;
X /* end treasure type 7 */
X
X case 8: /* treasure type 8 */
X switch (whichtreasure)
X {
X case 1:
X addstr("You have found a healing potion.\n");
X Player.p_poison = MIN(-2.0, Player.p_poison - 2.0);
X break;
X
X case 2:
X addstr("You have discovered a transporter. Do you wish to go anywhere ? ");
X ch = getanswer("NY", FALSE);
X addstr("\n\n");
X if (ch == 'Y')
X {
X double x, y;
X
X addstr("X Y Coordinates ? ");
X getstring(Databuf, SZ_DATABUF);
X sscanf(Databuf, "%F %F", &x, &y);
X altercoordinates(x, y, A_FORCED);
X }
X break;
X
X case 3:
X dtemp = ROLL(10.0 + Circle / 1.2, Circle * 3.0 + 30.0);
X printw("You've found a +%.0f sword!\n", dtemp);
X if (dtemp >= Player.p_sword)
X Player.p_sword = dtemp;
X else
X SOMEBETTER();
X break;
X }
X break;
X /* end treasure type 8 */
X
X case 10:
X case 11:
X case 12:
X case 13: /* treasure types 10 - 13 */
X if (random() < 0.33)
X {
X if (Curmonster.m_treasuretype == 10)
X {
X addstr("You've found a pair of elven boots!\n");
X Player.p_quickness += 2.0;
X break;
X }
X else if (Curmonster.m_treasuretype == 11
X && !Player.p_palantir)
X {
X addstr("You've acquired Saruman's palantir.\n");
X Player.p_palantir = TRUE;
X break;
X }
X else if (Player.p_ring.ring_type == R_NONE
X && Player.p_specialtype < SC_COUNCIL
X && (Curmonster.m_treasuretype == 12
X || Curmonster.m_treasuretype == 13))
X /* roll up a ring */
X {
X if (random() < 0.8)
X /* regular rings */
X {
X if (Curmonster.m_treasuretype == 12)
X {
X whichtreasure = R_NAZREG;
X temp = 35;
X }
X else
X {
X whichtreasure = R_DLREG;
X temp = 0;
X }
X }
X else
X /* bad rings */
X {
X whichtreasure = R_BAD;
X temp = 15 + Statptr->c_ringduration + (int) ROLL(0,5);
X }
X
X addstr("You've discovered a ring. Will you pick it up ? ");
X ch = getanswer("NY", FALSE);
X addstr("\n\n");
X
X if (ch == 'Y')
X {
X Player.p_ring.ring_type = whichtreasure;
X Player.p_ring.ring_duration = temp;
X }
X
X break;
X }
X }
X /* end treasure types 10 - 13 */
X /* fall through to treasure type 9 if no treasure from above */
X
X case 9: /* treasure type 9 */
X switch (whichtreasure)
X {
X case 1:
X if (Player.p_level <= 1000.0
X && Player.p_crowns <= 3
X && Player.p_level >= 10.0)
X {
X addstr("You have found a golden crown!\n");
X ++Player.p_crowns;
X break;
X }
X /* fall through otherwise */
X
X case 2:
X addstr("You've been blessed!\n");
X Player.p_blessing = TRUE;
X Player.p_sin /= 3.0;
X Player.p_energy = Player.p_maxenergy + Player.p_shield;
X Player.p_mana += 100.0 * Circle;
X break;
X
X case 3:
X dtemp = ROLL(1.0, Circle / 5.0 + 5.0);
X dtemp = MIN(dtemp, 99.0);
X printw("You have discovered some +%.0f quicksilver!\n",dtemp);
X if (dtemp >= Player.p_quksilver)
X Player.p_quksilver = dtemp;
X else
X SOMEBETTER();
X break;
X }
X break;
X /* end treasure type 9 */
X }
X }
X}
X/**/
X/************************************************************************
X/
X/ FUNCTION NAME: cursedtreasure()
X/
X/ FUNCTION: take care of cursed treasure
X/
X/ AUTHOR: E. A. Estes, 12/4/85
X/
X/ ARGUMENTS: none
X/
X/ RETURN VALUE: none
X/
X/ MODULES CALLED: waddstr()
X/
X/ GLOBAL INPUTS: Player, *stdscr
X/
X/ GLOBAL OUTPUTS: Player
X/
X/ DESCRIPTION:
X/ Handle cursed treasure. Look for amulets and charms to save
X/ the player from the curse.
X/
X/************************************************************************/
X
Xcursedtreasure()
X{
X if (Player.p_charms > 0)
X {
X addstr("But your charm saved you!\n");
X --Player.p_charms;
X }
X else if (Player.p_amulets > 0)
X {
X addstr("But your amulet saved you!\n");
X --Player.p_amulets;
X }
X else
X {
X Player.p_energy = (Player.p_maxenergy + Player.p_shield) / 10.0;
X Player.p_poison += 0.25;
X }
X}
X/**/
X/************************************************************************
X/
X/ FUNCTION NAME: scramblestats()
X/
X/ FUNCTION: scramble some selected statistics
X/
X/ AUTHOR: E. A. Estes, 12/4/85
X/
X/ ARGUMENTS: none
X/
X/ RETURN VALUE: none
X/
X/ MODULES CALLED: floor(), random()
X/
X/ GLOBAL INPUTS: Player
X/
X/ GLOBAL OUTPUTS: Player
X/
X/ DESCRIPTION:
X/ Swap a few player statistics randomly.
X/
X/************************************************************************/
X
Xscramblestats()
X{
Xdouble dbuf[6]; /* to put statistic in */
Xdouble dtemp1, dtemp2; /* for swapping values */
Xregister int first, second; /* indices for swapping */
Xregister double *dptr; /* pointer for filling and emptying buf[] */
X
X /* fill buffer */
X dptr = &dbuf[0];
X *dptr++ = Player.p_strength;
X *dptr++ = Player.p_mana;
X *dptr++ = Player.p_brains;
X *dptr++ = Player.p_magiclvl;
X *dptr++ = Player.p_energy;
X *dptr = Player.p_sin;
X
X /* pick values to swap */
X first = (int) ROLL(0, 5);
X second = (int) ROLL(0, 5);
X
X /* swap values */
X dptr = &dbuf[0];
X dtemp1 = dptr[first];
X /* this expression is split to prevent a compiler loop on some compilers */
X dtemp2 = dptr[second];
X dptr[first] = dtemp2;
X dptr[second] = dtemp1;
X
X /* empty buffer */
X Player.p_strength = *dptr++;
X Player.p_mana = *dptr++;
X Player.p_brains = *dptr++;
X Player.p_magiclvl = *dptr++;
X Player.p_energy = *dptr++;
X Player.p_sin = *dptr;
X}
!EOR!
echo x - convert.c
sed 's/^X//' > convert.c << '!EOR!'
X/*
X * Convert Phantasia 3.3.1 and 3.3.1+ characs file format to 3.3.2
X *
X */
X
X#include "include.h"
X#include "oldplayer.h"
X
Xstruct oldplayer Oldplayer; /* old format structure */
Xstruct player Newplayer; /* new format structure */
X
Xchar Oldpfile[] = DEST/characs"; /* old format file */
Xchar Newpfile[] = DEST/newcharacs"; /* new format file */
X
X/************************************************************************
X/
X/ FUNCTION NAME: main()
X/
X/ FUNCTION: convert old Phantasia player file to new format
X/
X/ AUTHOR: C. Robertson, 9/1/85 E. A. Estes, 3/12/86
X/
X/ ARGUMENTS: none
X/
X/ RETURN VALUE: none
X/
X/ MODULES CALLED: time(), exit(), fread(), fopen(), srand(), floor(),
X/ random(), strcmp(), fwrite(), strcpy(), fclose(), fprintf()
X/
X/ GLOBAL INPUTS: _iob[], Oldplayer, Newplayer
X/
X/ GLOBAL OUTPUTS: Oldplayer, Newplayer
X/
X/ DESCRIPTION:
X/ Read in old player structures and write out to new file in
X/ new format.
X/ Old player file is unmodified.
X/ New file is "DEST/newcharacs".
X/ #define PHANTPLUS to convert from 3.3.1+.
X/
X/************************************************************************/
X
Xmain()
X{
XFILE *oldcharac, *newcharac; /* to open old and new files */
X
X if ((oldcharac = fopen(Oldpfile, "r")) == NULL)
X {
X fprintf(stderr, "Cannot open original character file!\n");
X exit(1);
X }
X
X if ((newcharac = fopen(Newpfile, "w")) == NULL)
X {
X fprintf(stderr, "Cannot create new character file!\n");
X exit(1);
X }
X
X srand((unsigned) time((long *) NULL)); /* prime random numbers */
X
X while (fread((char *) &Oldplayer, sizeof(struct oldplayer), 1, oldcharac) == 1)
X /* read and convert old structures into new */
X {
X Newplayer.p_experience = Oldplayer.o_experience;
X Newplayer.p_level = (double) Oldplayer.o_level;
X Newplayer.p_strength = Oldplayer.o_strength;
X Newplayer.p_sword = Oldplayer.o_sword;
X Newplayer.p_might = 0.0; /* game will calculate */
X Newplayer.p_energy = Oldplayer.o_energy;
X Newplayer.p_maxenergy = Oldplayer.o_maxenergy;
X Newplayer.p_shield = Oldplayer.o_shield;
X Newplayer.p_quickness = (double) Oldplayer.o_quickness;
X Newplayer.p_quksilver = (double) Oldplayer.o_quksilver;
X Newplayer.p_speed = 0.0; /* game will calculate */
X Newplayer.p_magiclvl = Oldplayer.o_magiclvl;
X Newplayer.p_mana = Oldplayer.o_mana;
X Newplayer.p_brains = Oldplayer.o_brains;
X Newplayer.p_poison = Oldplayer.o_poison;
X Newplayer.p_gold = Oldplayer.o_gold;
X Newplayer.p_gems = Oldplayer.o_gems;
X Newplayer.p_sin = Oldplayer.o_sin;
X Newplayer.p_x = Oldplayer.o_x;
X Newplayer.p_y = Oldplayer.o_y;
X Newplayer.p_1scratch = Oldplayer.o_1scratch;
X Newplayer.p_2scratch = Oldplayer.o_2scratch;
X
X Newplayer.p_ring.ring_type = Oldplayer.o_ring.ring_type;
X Newplayer.p_ring.ring_duration = Oldplayer.o_ring.ring_duration;
X Newplayer.p_ring.ring_inuse = FALSE;
X
X Newplayer.p_age = (long) Oldplayer.o_degenerated * N_AGE;
X
X Newplayer.p_degenerated = Oldplayer.o_degenerated + 1;
X
X /* convert character type into character type and special type */
X
X if (Oldplayer.o_type < 0)
X /* player with crown */
X Oldplayer.o_type = -Oldplayer.o_type;
X
X if (Oldplayer.o_type == 99)
X /* valar */
X {
X Newplayer.p_specialtype = SC_VALAR;
X Newplayer.p_type = (short) ROLL(C_MAGIC, C_EXPER - C_MAGIC + 1);
X Newplayer.p_lives = Oldplayer.o_ring.ring_duration;
X }
X else if (Oldplayer.o_type == 90)
X /* ex-valar */
X {
X Newplayer.p_specialtype = SC_EXVALAR;
X Newplayer.p_type = (short) ROLL(C_MAGIC, C_EXPER - C_MAGIC + 1);
X Newplayer.p_lives = 0;
X }
X else if (Oldplayer.o_type > 20)
X /* council of wise */
X {
X Newplayer.p_specialtype = SC_COUNCIL;
X Newplayer.p_type = Oldplayer.o_type - 20;
X Newplayer.p_lives = Oldplayer.o_ring.ring_duration;
X }
X else if (Oldplayer.o_type > 10)
X /* king */
X {
X Newplayer.p_specialtype = SC_KING;
X Newplayer.p_type = Oldplayer.o_type - 10;
X Newplayer.p_lives = 0;
X }
X else
X /* normal player */
X {
X Newplayer.p_specialtype = SC_NONE;
X Newplayer.p_type = Oldplayer.o_type;
X Newplayer.p_lives = 0;
X }
X
X Newplayer.p_lives = 0;
X Newplayer.p_crowns = Oldplayer.o_crowns;
X Newplayer.p_charms = Oldplayer.o_charms;
X Newplayer.p_amulets = Oldplayer.o_amulets;
X Newplayer.p_holywater = Oldplayer.o_holywater;
X Newplayer.p_lastused = Oldplayer.o_lastused;
X
X /* convert status and name into status */
X
X Newplayer.p_status = Oldplayer.o_status + S_OFF;
X if (strcmp(Oldplayer.m_name, "<null>") == 0)
X /* unused recored */
X Newplayer.p_status = S_NOTUSED;
X if (Oldplayer.o_quickness < 0)
X /* hung up player */
X {
X Newplayer.p_quickness = (double) Oldplayer.o_tampered;
X Oldplayer.o_tampered = T_OFF;
X Newplayer.p_status = S_HUNGUP;
X }
X
X Newplayer.p_tampered = Oldplayer.o_tampered + T_OFF;
X Newplayer.p_istat = I_OFF;
X
X Newplayer.p_palantir = Oldplayer.o_palantir;
X Newplayer.p_blessing = Oldplayer.o_blessing;
X Newplayer.p_virgin = Oldplayer.o_virgin;
X Newplayer.p_blindness = Oldplayer.o_blindness;
X
X strcpy(Newplayer.p_name, Oldplayer.o_name);
X strcpy(Newplayer.p_password, Oldplayer.o_password);
X strcpy(Newplayer.p_login, Oldplayer.o_login);
X
X /* write new structure */
X fwrite((char *) &Newplayer, sizeof(Newplayer), 1, newcharac);
X }
X
X fclose(oldcharac); /* close files */
X fclose(newcharac);
X
X exit(0);
X}
X/**/
X/************************************************************************
X/
X/ FUNCTION NAME: random()
X/
X/ FUNCTION: return a random number between 0.0 < 1.0
X/
X/ AUTHOR: E. A. Estes, 2/7/86
X/
X/ ARGUMENTS: none
X/
X/ RETURN VALUE: random number
X/
X/ MODULES CALLED: rand()
X/
X/ GLOBAL INPUTS: none
X/
X/ GLOBAL OUTPUTS: none
X/
X/ DESCRIPTION:
X/ Return a random number.
X/
X/************************************************************************/
X
Xdouble
Xrandom()
X{
X if (sizeof(int) != 2)
X return((double) (rand() & 0x7fff) / 32768.0);
X else
X return((double) rand() / 32768.0);
X}
!EOR!